
#include "loirey_SparseVector.h"

using namespace loirey;

// [*] CSparseVector

CSparseVector::CSparseVector()
{
	Clear();
}

size_t loirey::CSparseVector::GetIVPairMemorySize()
{
	return sizeof(int) + sizeof(double);
}

size_t CSparseVector::GetVectorMemorySize() const
{
	return sizeof(Length)
		+ ((size_t)Length) * sizeof(*IndexList.pElement)
		+ ((size_t)Length) * sizeof(*ValueList.pElement);
}

void CSparseVector::WriteToFile( FILE* FOUT ) const
{
	CDataStructureTools::my_fwrite_single(FOUT, Length);
	CDataStructureTools::my_fwrite(FOUT, IndexList);
	CDataStructureTools::my_fwrite(FOUT, ValueList);
}

void CSparseVector::ReadFromFile( FILE* FIN )
{
	CDataStructureTools::my_fread_single(FIN, Length);
	CDataStructureTools::my_fread(FIN, IndexList, Length);
	CDataStructureTools::my_fread(FIN, ValueList, Length);
}

void CSparseVector::myInit( const CSimpleTypeArray<double>& DenseValueList )
{
	int i;
	const double* QD;
	this->Clear();
	QD = DenseValueList.pElement;
	for ( i = 0; i < (int)DenseValueList.Size; ++i )
	{
		if (*QD>-MAXIMUM_DOUBLE_NUM_C && *QD<+MAXIMUM_DOUBLE_NUM_C) continue;
		IndexList.PushBack(i);
		ValueList.PushBack(*(QD++));
	}
	Length = (int)IndexList.Size;
}

void CSparseVector::myInit( const CSparseVector& Another )
{
	this->Length = Another.Length;
	this->IndexList = Another.IndexList;
	this->ValueList = Another.ValueList;
}

void CSparseVector::myInit( const CSimpleTypeArray<int>& IndexList, const CSimpleTypeArray<double>& ValueList )
{
	this->Length = (int)IndexList.Size;
	this->IndexList = IndexList;
	this->ValueList = ValueList;
}

void CSparseVector::Clear()
{
	Length = 0;
	IndexList.Clear();
	ValueList.Clear();
}

void CSparseVector::PushBack( int Index, double Value )
{
	++Length;
	IndexList.PushBack(Index);
	ValueList.PushBack(Value);
}

void CSparseVector::SortByIndex()
{
	int i;
	CSimpleTypeArray<CIVPair> tList;
	tList.Resize(Length);
	CIVPair* Pp = tList.pElement;
	int* Px = IndexList.pElement;
	double* Py = ValueList.pElement;
	for ( i = 0; i < Length; ++i )
	{
		Pp[i].Index = Px[i];
		Pp[i].Value = Py[i];
	}
	sort(Pp, Pp + Length, CIVPair::CompareByIndex);
	for ( i = 0; i < Length; ++i )
	{
		Px[i] = Pp[i].Index;
		Py[i] = Pp[i].Value;
	}
}

void CSparseVector::SortByValue()
{
	int i;
	CSimpleTypeArray<CIVPair> tList;
	tList.Resize(Length);
	CIVPair* Pp = tList.pElement;
	int* Px = IndexList.pElement;
	double* Py = ValueList.pElement;
	for ( i = 0; i < Length; ++i )
	{
		Pp[i].Index = Px[i];
		Pp[i].Value = Py[i];
	}
	sort(Pp, Pp + Length, CIVPair::CompareByValue);
	for ( i = 0; i < Length; ++i )
	{
		Px[i] = Pp[i].Index;
		Py[i] = Pp[i].Value;
	}
}

void CSparseVector::DeepClear()
{
	Length = 0;
	IndexList.DeepClear();
	ValueList.DeepClear();
}

void CSparseVector::Swap( CSparseVector& Another )
{
	int t = Length; Length = Another.Length; Another.Length = t;
	IndexList.Swap(Another.IndexList);
	ValueList.Swap(Another.ValueList);
}

double CSparseVector::GetValue( int Index ) const
{
	int aa = (int)(lower_bound(IndexList.Begin(), IndexList.End(), Index) - IndexList.Begin());
	if (aa<(int)IndexList.Size && IndexList.pElement[aa]==Index)
		return ValueList.pElement[aa];
	else
		return 0.0;
}

void CSparseVector::Normalize( CMyNormalizer* pNormalizer )
{
	pNormalizer->Normalize(ValueList);
}

